package loader

import (
	"fmt"
	"reflect"
	"strconv"
	"unsafe"
)

type DesignTable[T any] struct {
	all []*T
}

func (t *DesignTable[T]) Load(designFields []DesignField, datas [][]string) {
	dataSlice := make([]*T, 0, len(datas))

	var temp T
	rType := reflect.TypeOf(&temp)

	for _, data := range datas {
		objPtr := reflect.New(rType.Elem())
		rValue := objPtr.Elem()

		for i := 0; i < len(designFields) && i < len(data); i++ {
			fieldName := designFields[i].FieldName
			rField := rValue.FieldByName(fieldName)

			fieldData := data[i]
			formValue(rField, fieldData)
		}
		dataObj := rValue.Interface().(T)
		dataSlice = append(dataSlice, &dataObj)
	}
	t.all = dataSlice
	fmt.Println(t.all[0])
}

func formValue(objField reflect.Value, value string) {
	if objField.Kind() == reflect.Int32 {
		i32, err := strconv.ParseInt(value, 10, 32)
		if err == nil {
			rValue := reflect.ValueOf(i32)
			if objField.CanSet() {
				objField.SetInt(rValue.Interface().(int64))
			} else {
				objField = reflect.NewAt(objField.Type(), unsafe.Pointer(objField.UnsafeAddr())).Elem()
				objField.SetInt(rValue.Interface().(int64))
			}
		}
	} else if objField.Kind() == reflect.Int64 {
		i64, err := strconv.ParseInt(value, 10, 64)
		if err == nil {
			rValue := reflect.ValueOf(i64)
			if objField.CanSet() {
				objField.SetInt(rValue.Interface().(int64))
			} else {
				objField = reflect.NewAt(objField.Type(), unsafe.Pointer(objField.UnsafeAddr())).Elem()
				objField.SetInt(rValue.Interface().(int64))
			}
		}
	} else if objField.Kind() == reflect.String {
		rValue := reflect.ValueOf(value)
		if objField.CanSet() {
			objField.SetString(rValue.Interface().(string))
		} else {
			objField = reflect.NewAt(objField.Type(), unsafe.Pointer(objField.UnsafeAddr())).Elem()
			objField.SetString(rValue.Interface().(string))
		}
	}
}

func (t *DesignTable[T]) All() []*T {
	return t.all
}
